<!--  -->
<template>
  <div class="app-container">
    <!-- START 卡片视图 START -->
    <el-card style="margin-bottom: 10px;">
      <!-- START添加和展开/折叠按扭区域 START -->
      <el-row :gutter="10">
        <el-col :span="5">
          <el-input
            v-model="menuName"
            size="small"
            placeholder="请输入菜单名称"
            clearable
            @clear="getMenusList"
          />
        </el-col>
        <el-col :span="2">
          <el-button
            icon="el-icon-search"
            type="primary"
            size="mini"
            @click="getMenus"
          >搜索</el-button>
        </el-col>
        <el-col :span="6">
          <el-button v-hasPermi="['/system/menu/saveMenu']" type="primary" plain size="mini" icon="el-icon-plus" @click="openRightDialog">新增</el-button>
          <el-button type="info" plain size="mini" icon="el-icon-sort" @click="toggleExpandAll">展开/折叠</el-button>
        </el-col>
      </el-row>
      <!--  END 添加和展开/折叠按扭区域 END -->
    </el-card>
    <!-- END 卡片视图 END -->

    <!-- START 权限列表区域 START -->
    <el-card>
      <el-table
        v-if="refreshTable"
        :data="menuList"
        style="width: 100%; margin-bottom: 20px"
        row-key="id"
        :stripe="true"
        :default-expand-all="isExpandAll"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      >
        <el-table-column label="权限名称" width="240px" align="left">
          <template slot-scope="{row}">
            <span>{{ row.name }}</span>
          </template>
        </el-table-column>
        <el-table-column label="请求路径" width="240px" align="center">
          <template slot-scope="{row}">
            <span>{{ row.url }}</span>
          </template>
        </el-table-column>
        <el-table-column label="组件路径" width="160px" align="center">
          <template slot-scope="{row}">
            <span>{{ row.path }}</span>
          </template>
        </el-table-column>
        <el-table-column label="组件名称" width="180px" align="center">
          <template slot-scope="{row}">
            <span v-if="row.component != null">{{ row.component }}.vue</span>
            <span v-else />
          </template>
        </el-table-column>
        <el-table-column label="图标" width="80px" align="center">
          <template slot-scope="{row}">
            <span :class="row.iconCls" />
            <!-- 因为小图标来自两个不同地方，一个是Element-ui，另一个是本地，所以我们将@/layout/components/Sidebar/Item.vue组件导入进来，使用这个组件来显示小图标，这个Item.vue组件中对这两个不同位置的小图标进行了判断-->
            <item :icon="row.iconCls" />
          </template>
        </el-table-column>
        <!-- 菜单类别：menuLevel字段，1、代表菜单  2、按扭-->
        <el-table-column label="菜单类别" width="110px" align="center">
          <template slot-scope="{row}">
            <span v-if="row.menuLevel == 3">按扭</span>
            <span v-else>菜单</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="200px" align="center">
          <!-- 使用作用域插槽的形式为[权限等级]列自定义内容，使用scope来接收所有的数据 -->
          <template slot-scope="scope">
            <!-- 编辑按扭 -->
            <el-button
              icon="el-icon-edit"
              type="primary"
              size="mini"
              plain
              round
              @click="showEditDialog(scope.row.id)"
              v-hasPermi="['/system/menu/updateMenu']"
            >编辑</el-button>
            <!-- 删除按扭 -->
            <el-button
              icon="el-icon-delete"
              type="danger"
              size="mini"
              plain
              round
              @click="delRightById(scope.row.id)"
              v-hasPermi="['/system/menu/delMenu']"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!-- END 权限列表区域 END-->

    <!-- START 添加菜单权限对话框 START -->
    <el-dialog
      :title="textMap[dialogStatus]"
      :visible.sync="addRightDialogVisible"
      width="40%"
    >
      <el-form ref="addFormRef" :rules="addFormRules" :model="addForm" label-position="left" label-width="80px" style="width: 550px; margin-left:15px;">
        <el-form-item label="上级菜单" prop="name">
          <tree-select
            ref="treeRef"
            :data="treeMenuList"
            :default-props="defaultProps"
            :node-key="nodeKey"
            :checked-keys="defaultCheckedKeys"
            @popoverHide="popoverHide"
          />
        </el-form-item>
        <el-form-item label="菜单等级" prop="menuLevel">
          <el-radio-group v-model="addForm.menuLevel">
            <el-radio :label="1">一级</el-radio>
            <el-radio :label="2">二级</el-radio>
            <el-radio :label="3">三级</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单图标" prop="iconCls">
          <el-popover
            placement="bottom-start"
            width="460"
            trigger="click"
            @show="$refs['iconSelect'].reset()"
          >
            <IconSelect ref="iconSelect" @selected="selected" />
            <el-input slot="reference" v-model="addForm.iconCls" placeholder="点击选择图标" readonly>
              <svg-icon
                v-if="addForm.iconCls"
                slot="prefix"
                :icon-class="addForm.iconCls"
                class="el-input__icon"
                style="height: 32px;width: 16px;"
              />
              <i v-else slot="prefix" class="el-icon-search el-input__icon" />
            </el-input>
          </el-popover>
        </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="菜单名称" prop="name">
              <el-input v-model="addForm.name" placeholder="请输入菜单名称" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="权限路径" prop="url">
              <el-input v-model="addForm.url" placeholder="请输入权限路径" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="路由地址" prop="path">
              <el-input v-model="addForm.path" placeholder="请输入路由地址" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="组件地址" prop="url">
              <el-input v-model="addForm.component" placeholder="请输入组件地址" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancelEvent() ">取 消</el-button>
        <el-button type="primary" @click="dialogStatus==='create'?insertData():updateData()">确 定</el-button>
      </span>
    </el-dialog>
    <!-- END 添加菜单权限对话框 END -->
  </div>
</template>

<script>
// 这里可以导入其他文件（比如：组件，工具js，第三方插件js，json文件，图片文件等等）
// 例如：import 《组件名称》 from '《组件路径》';
// Item.vue组件用于显示小图标
import Item from '@/layout/components/Sidebar/Item'
import TreeSelect from '@/components/TreeSelect'
import IconSelect from '@/components/IconSelect'

import { getAllMenuList, saveMenu, delMenuById, findByMenuId, updateMenu } from '@/api/menu'
export default {
// import引入的组件需要注入到对象中才能使用
  components: {
    Item, TreeSelect, IconSelect
  },
  // props实现父子组件传递数据
  props: {},
  data() {
    // 这里存放数据
    return {
      // 菜单列表
      menuList: [],
      // true则会显示正在加载的图标
      listLoading: true,
      // 展开/折叠通过下面属性来控制
      isExpandAll: false,
      // 是否重新渲染表格
      refreshTable: true,
      menuName: '',
      // 用于控制[添加菜单]对话框的显示与隐藏，true表示显示,false表示隐藏
      addRightDialogVisible: false,
      // 因为添加和编辑用户共用一个弹出窗口，通过dialogStatus来动态设置弹出窗口的标题。
      dialogStatus: '',
      textMap: {
        create: '添加菜单',
        update: '编辑菜单'
      },
      // 用于绑定[添加菜单]对话框的表单数据
      addForm: {
        id: undefined,
        url: '',
        path: null,
        component: null,
        name: '',
        iconCls: '',
        enabled: 1,
        menuLevel: 1,
        parentId: 0
      },
      // 添加菜单表单验证规则对象
      addFormRules: {
        // 为权限名称的所在的表单项定义验证规则
        name: [
          { required: true, message: '请输入菜单名称', trigger: 'blur' },
          { min: 3, max: 20, message: '菜单名称的长度在3~20个字符之间', trigger: 'blur' }
        ]
      },
      // 添加权限对话框中父级权限树形控件的数据源
      rithsList: [],
      defaultProps: {
        children: 'children', // 树形控件的子节点
        label: 'name' // 以权限名作为树形控件的显示值
      },
      nodeKey: 'id', // 以权限编号作为当前树形控件中节点的key
      // 默认选择树形控件中根节点
      defaultCheckedKeys: [],
      // 添加菜单对话框中，上级菜单下拉框的数据绑定到如下变量中
      treeMenuList: []
    }
  },
  // 监听属性 类似于data概念
  computed: {},
  // 监控data中的数据变化
  watch: {
    // 监听修改权限对话框中的addForm对象值的变化，一旦addForm的值发生改变就进入到下面事件中，我们再使用$emit调用子组件TreeSelect.vue中updateCheckedKey方法，实现将当前要修改的权限的父级权限在树形控件中选中
    addForm: function() { // 语法：属性名:function(){} 即可实现对某个属性的数据进行监听
      this.$nextTick(function() {
        this.$refs.treeRef.$emit('updateCheckedKey')
      })
    }
  },
  // 生命周期 - 创建完成（可以访问当前this实例）
  created() {
    // 在窗口加载事件中，直接调用getMenusList()查询出菜单列表信息
    this.getMenusList()
  },
  // 生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {

  },
  beforeCreate() {
  }, // 生命周期 - 创建之前
  beforeMount() {
  }, // 生命周期 - 挂载之前
  beforeUpdate() {
  }, // 生命周期 - 更新之前
  updated() {
  }, // 生命周期 - 更新之后
  beforeDestroy() {
  }, // 生命周期 - 销毁之前
  destroyed() {
  }, // 生命周期 - 销毁完成
  activated() {
  },
  // 方法集合
  methods: {
    // 编辑按扭的点击事件
    showEditDialog(id) {
      // 重置addForm对象
      this.resetMenu()
      // 显示编辑/添加菜单对话框
      this.addRightDialogVisible = true
      // 动态修改[编辑对话框窗口标题]
      this.dialogStatus = 'update'
      // id为要修改的菜单id
      // 发送请求通过菜单ID查询菜单详情对象信息
      findByMenuId(id).then((res) => {
        this.addForm = res
        // 设置父级权限所在的下拉框树形控件指定节点被选中
        this.defaultCheckedKeys = [res.parentId]
      }).catch((err) => {
        this.$message.error(err)
      })
    },
    // 修改对话框弹出窗口里[确认]按扭的点击事件
    updateData() {
      updateMenu(this.addForm).then((res) => {
        if (res.code === 200) {
          // 是修改成功
          this.$message.success(res.message)
          // 将[修改菜单弹出对话框窗口]给关闭掉
          this.addRightDialogVisible = false
          // 修改成功后，还需要再调用getMenusList()获取最新的角色列表信息
          this.getMenusList()
        } else {
          return this.$message.error(res.message)
        }
      }).catch((err) => {
        this.$message.error(err)
      })
    },
    // [删除]按扭的点击事件, id为要删除的菜单ID
    delRightById(id) {
      this.$confirm(
        '确定要删除当前菜单吗?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then((res) => {
        delMenuById(id).then((res) => {
          if (res.code !== 200) return this.$message.error(res.message)
          this.$message.success(res.message)
          // 删除成功后，再刷新角色列表数据
          this.getMenusList()
          // 删除菜单权限成功后，获取最新的菜单列表信息，并把它保存到Vuex中
          this.$store.dispatch('menu/initRouters').then((data) => {
            // 将fmtRouters添加router路由中，即保存到router/index.js中
            this.$router.addRoutes(data) // 动态添加路由
          }).catch((err) => {
            console.log(err)
          })
        }).catch(() => {
          this.$message.error('删除菜单失败！')
        })
      }).catch(() => {
        return this.$message.info('您取消了删除！')
      })
    },
    // 选择图标
    selected(name) {
      // 将选中的小图标赋值给addForm.iconCls
      this.addForm.iconCls = name
    },
    // [添加/编辑菜单]对话框中[确认]按扭的点击事件
    insertData() {
      this.$refs['addFormRef'].validate((valid) => {
        if (valid) {
        // 调用role.js中的saveRole方法发送请求到后端实现保存新增的角色信息
          saveMenu(this.addForm).then((res) => {
          // false后隐藏添加操作员对话框
            this.addRightDialogVisible = false
            if (res.code === 200) {
            // 新增成功后，再刷新角色列表数据
              this.getMenusList()
              // 清空[添加权限]表单中的对象数据
              this.resetMenu()
              this.$message({
                title: '提示',
                message: res.message,
                type: 'success',
                duration: 2000
              })
            } else {
              this.$message({
                title: '提示',
                message: res.message,
                type: 'error',
                duration: 2000
              })
            }
          }).catch((err) => {
            console.log(err)
          })
        }
      })
    },
    // 添加权限按扭的点击事件
    openRightDialog() {
      // 重置addForm对象
      this.resetMenu()
      // 将添加权限对话框显示出来
      this.addRightDialogVisible = true
      // 因为[添加菜单]与[编辑菜单]共用同一个对话框，当dialogStatus等于create时，此对话框的标题为[添加菜单]
      // 并且点击[确认]按扭时，将会触的是insertDate()这个新增菜单的方法。
      this.dialogStatus = 'create'
    },
    // 重置Menu对象
    resetMenu() {
      this.addForm = {
        id: undefined,
        url: '',
        path: null,
        component: null,
        name: '',
        iconCls: '',
        enabled: 1,
        menuLevel: 1,
        parentId: 0
      }
    },
    cancelEvent() {
      // 重置addForm对象
      this.resetMenu()
      // 将[添加/编辑菜单]对话框进行隐藏
      this.addRightDialogVisible = false
    },
    // 搜索按扭的点击事件
    getMenus() {
      // menus用来保存通过菜单名称模糊查询到的菜单列表
      const menus = []
      if (this.menuName) { // 如果用户在文本框中输入了菜单名称
        this.queryMenu(this.menuName, this.menuList, menus)
        // 将通过菜单名称模糊查询到的菜单列表赋值给menuList，达到更新菜单列表数据
        this.menuList = menus
      } else {
        this.getMenusList()
      }
    },
    // menuName为菜单名称查询条件， data为菜单列表  menus保存按菜单名称模糊查询得到的数据
    queryMenu(menuName, data, menus) {
      data.forEach((menu) => {
        if (menu.name.indexOf(menuName) !== -1) {
          menus.push(menu)
        } else {
          if (menu.children != null && menu.children.length !== 0) {
            this.queryMenu(menuName, menu.children, menus)
          }
        }
      })
    },
    // 开展和折叠按扭的点击事件
    toggleExpandAll() {
      this.refreshTable = false
      this.isExpandAll = !this.isExpandAll
      this.$nextTick(() => {
        this.refreshTable = true
      })
    },
    // 查询权限列表
    getMenusList() {
      // true时，表格中就会出现正在加载图标
      this.listLoading = true
      getAllMenuList().then((res) => {
        // false时，正在加载图标就会消失
        this.listLoading = false
        this.menuList = res

        // 清空[添加权限]对话框中上级菜单下拉框中的数据(新增/编辑/删除菜单都会调用getMenusList()查询最新的权限列表，这时如果不加下面的if，会在[上菜单菜单]下拉框中追加多次菜单列表数据)
        if (this.treeMenuList && this.treeMenuList.length > 0) {
          this.treeMenuList = []
        }
        // 往this.treeMenuList数组中第一位置添加数据
        this.treeMenuList.push({
          name: '主目录',
          id: 1,
          children: this.menuList
        })
      }).catch((err) => {
        console.log(err)
        this.$message({
          title: '提示',
          message: '查询角色列表失败!',
          type: 'error',
          duration: 2000
        })
      })
    },
    // 下拉菜单节点选中事件，checkedIds为选中节点的nodeKey值，checkedData为选中节点对象
    // checkedData.id得到菜单编号、checkedData.name得到菜单名
    popoverHide(checkedIds, checkedData) {
      console.log(checkedIds)
      console.log(checkedData)
      this.addForm.parentId = checkedData.id
    }
  } // 如果页面有keep-alive缓存功能，这个函数会触发
}
</script>
<style scoped>

</style>
